<template>
    <div class="drawer-layout" v-loading="loading">
        <!-- Header -->
        <div class="drawer-header">{{ form.id ? "编辑角色" : "新增角色" }}</div>

        <!-- Body -->
        <div class="drawer-body">
            <el-form ref="formRef" :model="form" label-width="80px">
                <el-form-item
                    label="角色名称"
                    prop="name"
                    :rules="{ required: true, message: '请输入角色名称' }"
                >
                    <el-input v-model="form.name" placeholder="请输入角色名称"/>
                </el-form-item>

                <el-form-item
                    label="唯一标识"
                    prop="tag"
                    :rules="{ required: true, message: '请输入唯一标识' }"
                >
                    <el-input v-model="form.tag" placeholder="请输入唯一标识"/>
                </el-form-item>

                <el-form-item label="角色描述">
                    <el-input type="textarea" rows="3" v-model="form.description" placeholder="请输入角色描述"/>
                </el-form-item>
                <el-form-item label="权限设置" :rules="{ required: true }">
                    <div>
                        <el-button @click="toggleExpand" :size="'small'">{{
                                isExpanded ? '全部收起' : '全部展开'
                            }}
                        </el-button>
                        <el-tree
                            ref="treeRef"
                            :data="menus"
                            :props="treeProps"
                            show-checkbox
                            node-key="id"
                            v-model:checked-keys="form.menus"
                            :default-expanded-keys="expandedKeys"
                            :check-strictly="true"
                            @check-change="onCheckChange"
                        ></el-tree>
                    </div>

                </el-form-item>

                <el-form-item label="状态" prop="state">
                    <el-radio-group v-model="form.state">
                        <el-radio
                            v-for="state in filter.state"
                            :key="state.key"
                            :value="state.key"
                        >
                            {{ state.label }}
                        </el-radio>
                    </el-radio-group>
                </el-form-item>
            </el-form>
        </div>

        <!-- Footer -->
        <div class="drawer-footer">
            <el-button @click="onCancel">取消</el-button>
            <el-button type="primary" @click="onSubmit" :loading="loading">确认</el-button>
        </div>
    </div>
</template>

<script setup lang="ts">
import {reactive, ref, watch} from "vue";
import {
    createRoleApi,
    getRoleDetailApi,
    getRoleFilterApi,
    getRoleMenusApi,
    updateRoleApi
} from "@/api/modules/setting.ts";
import type {FilterModel} from "@/models/filterModel.ts";
import {ElMessage} from "element-plus";

const loading = ref(false);

const treeRef = ref<any>(null);
const expandedKeys = ref<number[]>([]);
const isExpanded = ref(false);
const menus = ref<Menu.MenuOptions[]>([]);
const treeProps = {
    children: "children",
    label: "title",
    isLeaf: "isLeaf",
};

const props = defineProps<{ modelValue: boolean; roleID?: number }>();
const emit = defineEmits(["update:modelValue", "success"]);

const onCancel = () => {
    emit("update:modelValue", false);
};

// 确保树渲染完成再展开/收起
const toggleExpand = () => {
    if (!treeRef.value) return;
    if (isExpanded.value) {
        treeRef.value.store._getAllNodes().forEach((node: any) => {
            node.expanded = false;
        });
    } else {
        treeRef.value.store._getAllNodes().forEach((node: any) => {
            node.expanded = true;
        });
    }
    isExpanded.value = !isExpanded.value;
};

const getParentKeys = (id: number, nodes: any[]): number[] => {
    let parentKeys: number[] = [];
    for (const node of nodes) {
        if (node.id === id) {
            if (node.parent_id) {
                parentKeys.push(node.parent_id);
            }
            break;
        }
        if (node.children) {
            parentKeys = parentKeys.concat(getParentKeys(id, node.children));
        }
    }
    return parentKeys;
};

const getAllKeys = (nodes: Menu.MenuOptions[]): number[] => {
    let keys: number[] = [];
    nodes.forEach(node => {
        if (node.id != null) {
            keys.push(node.id);
        }
        if (node.children) {
            keys = keys.concat(getAllKeys(node.children));
        }
    })
    return keys;
};

function getDefaultForm(roleID = 0) {
    return {
        id: roleID,
        name: "",
        tag: "",
        state: "",
        description: "",
        menus: [] as number[],
    };
}

const form = reactive(getDefaultForm(props.roleID ?? 0));

function resetForm(roleID = 0) {
    Object.assign(form, getDefaultForm(roleID));
}

// 过滤器
const filter = reactive<FilterModel>({
    state: [],
});

// 获取状态列表
const loadFilters = async () => {
    const filterData = await getRoleFilterApi();
    filter.state = Object.entries(filterData.data.data.state || {}).map(
        ([key, label]) => ({key, label})
    );
    // 如果是新增，并且还没有选择状态 → 默认第一个
    if (!form.id && !form.state && filter.state.length > 0) {
        form.state = filter.state[0].key;
    }
};

const loadMenus = async () => {
    const menusData = await getRoleMenusApi();
    menus.value = menusData.data.data;
}

const isLeaf = (id: number, nodes: any[]): boolean => {
    for (const node of nodes) {
        if (node.id === id) {
            return !node.children || node.children.length === 0;
        }
        if (node.children) {
            if (isLeaf(id, node.children)) return true;
        }
    }
    return false;
};

const loadDetail = async (id: number) => {
    const detailData = await getRoleDetailApi({id: id});
    Object.assign(form, detailData.data.data);
    if (treeRef.value) {
        // 回显时选中父节点和子节点
        const checkedKeys = form.menus;
        treeRef.value.setCheckedKeys(checkedKeys);
    }
};

watch(
    () => props.modelValue,
    async (val) => {
        if (val) {
            loading.value = true;
            resetForm(props.roleID ?? 0);
            try {
                await loadFilters();
                await loadMenus();
                if (form.id > 0) {
                    await loadDetail(form.id);
                }
            } catch (error) {
                emit("update:modelValue", false);
                console.error(error);
            } finally {
                loading.value = false;
            }
        }
    },
    {immediate: true}
);

const submitting = ref(false);
// 提交
const onSubmit = async () => {
    if (submitting.value) return;
    submitting.value = true;
    try {
        const checked = treeRef.value?.getCheckedKeys() || [];
        const halfChecked = treeRef.value?.getHalfCheckedKeys() || [];
        form.menus = [...checked, ...halfChecked];
        if (form.id > 0) {
            const updateData = await updateRoleApi(form);
            ElMessage.success(updateData.message);
        } else {
            const createData = await createRoleApi(form);
            ElMessage.success(createData.message);
        }
        emit("success", {...form});
        emit("update:modelValue", false);
    } catch (error) {
        console.log(error);
    } finally {
        submitting.value = false;
    }
};
const onCheckChange = () => {
    const checkedKeys = treeRef.value.getCheckedKeys();
    const parentKeys = checkedKeys.map((id: number) => getParentKeys(id, menus.value)).flat();
    treeRef.value.setCheckedKeys([...new Set([...checkedKeys, ...parentKeys])]);
};
</script>

<style scoped>
.drawer-layout {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.drawer-header {
    flex: 0 0 60px;
    padding: 16px 20px;
    font-size: 18px;
    font-weight: 600;
    border-bottom: 1px solid #ebeef5;
}

.drawer-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 20px;
}

.drawer-footer {
    flex: 0 0 64px;
    padding: 12px 20px;
    border-top: 1px solid #ebeef5;
    background: #fff;
    text-align: right;
}

.drawer-footer .el-button + .el-button {
    margin-left: 12px;
}
</style>
